#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// structs
struct Event {
  // public
  char *_name;
  struct System *system;
};

struct System {
  // private
  char *_name;
  int32_t _descriptor;
  int16_t _index;
  bool _active;
  struct Event **_events;
  int _eventsCount;
  int _maxEventsCount;
  // public
  bool (*isActive)(struct System *this);
  void (*addEvent)(struct System *this, struct Event *event);
  struct Event *(*getEvent)(struct System *this);
};

// System class
typedef struct System System;

bool isActive(System *this) { return this->_active; }

void addEvent(System *this, struct Event *event) {
  if (this->_eventsCount + 1 == this->_maxEventsCount) {
    this->_events = (struct Event **)realloc(
        this->_events, sizeof(struct Event *) * (this->_maxEventsCount + 5));

    this->_maxEventsCount += 5;
  }

  this->_events[this->_eventsCount++] = event;
}

struct Event *getEvent(struct System *this) {
  return this->_events[--this->_eventsCount];
}

System *createSystem(char *name, int32_t descriptor, int16_t index,
                     bool active) {
  System *pointer = malloc(sizeof(System));

  pointer->_name = name;
  pointer->_descriptor = descriptor;
  pointer->_index = index;
  pointer->_active = active;

  pointer->_eventsCount = 0;
  pointer->_maxEventsCount = 5;
  pointer->_events = malloc(sizeof(struct Event *) * 5);

  pointer->isActive = isActive;
  pointer->addEvent = addEvent;
  pointer->getEvent = getEvent;

  return pointer;
}

// Event class
typedef struct Event Event;

Event *createEvent(char *name, System *system) {
  Event *pointer = malloc(sizeof(Event));

  pointer->_name = name;
  pointer->system = system;

  return pointer;
}

int main() {
  char systemName[] = "System";
  System *system = createSystem(systemName, 1, 1, true);

  char eventName[] = "click";
  Event *event = createEvent(eventName, system);
  Event *events[] = {event};

  system->addEvent(system, event);

  printf("event: %s\n", system->getEvent(system)->_name);
  printf("eventsCount: %d\n", system->_eventsCount);

  free(system->_events);
  free(system);
  free(event);

  return 0;
}
